package com.ruoyi.project.inner.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.ruoyi.project.common.JsonResult;

import com.ruoyi.project.inner.controller.dto.GardensMqttCallback;
import com.ruoyi.project.inner.mqtt.MqttMessageFactory;
import com.ruoyi.project.inner.mqtt.MqttTemplate;
import com.ruoyi.project.inner.service.GardensUserTerminalService;
import com.ruoyi.project.inner.service.MqttService;
import com.ruoyi.project.inner.utils.MacTopicUtil;
import org.eclipse.paho.mqttv5.common.MqttException;
import org.eclipse.paho.mqttv5.common.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.UUID;


/**
 * @author Squbi
 */
@Service
public class MqttServiceImpl implements MqttService {

    private static final Logger LOGGER = LoggerFactory.getLogger(MqttServiceImpl.class);

    @Autowired
    private MqttTemplate template;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private GardensUserTerminalService gardensUserTerminalService;

    private final MqttMessageFactory messageFactory = new MqttMessageFactory();

    @Override
    public JsonResult userCall(String type, String url, Object data) {
        String mac = gardensUserTerminalService.getUserTerminal();
        String json = data == null ? "" : JSON.toJSONString(data, SerializerFeature.WriteNullStringAsEmpty);
        String result = call(mac, new GardensMqttCallback(type, url, json));
        return JSON.parseObject(result, JsonResult.class);
    }

    @Override
    public String call(String mac, GardensMqttCallback callback) {
        String uuid = UUID.randomUUID().toString();
        callback.setUuid(uuid);
        MqttMessage message = messageFactory.createMessage(JSON.toJSONString(callback).getBytes());
        try {
            template.publish(MacTopicUtil.getMacCallbackTopic(mac), message);
        } catch (MqttException e) {
            throw new RuntimeException(e);
        }

        String result;
        int times = 0;
        String key = MacTopicUtil.getRedisKeyByMac(mac, uuid);
        while (true) {
            result = redisTemplate.opsForValue().get(key);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            times++;
            if (result != null || times == 50) {
                LOGGER.info("Redis get key timeout : {}", key);
                break;
            }
        }
        return result;
    }

    @Override
    public void subscribe(String topic, int qos) {
        try {
            template.subscribe(topic, qos);
        } catch (MqttException e) {
            throw new RuntimeException(e);
        }
    }
}
